//
//  DoorLock+MsgHandle.swift
//  ZhiTing
//
//  Created by iMac on 2022/5/10.
//

import Foundation

extension DoorLockUtil {
    // MARK: - 处理接受到的蓝牙数据包
    /// - Parameter data: 数据
    func handleReceivedData(data: Data) {
        guard let doorLock = doorLock else {
            print("锁不存在")
            return
        }
        
        guard let decrpytedData = decrypt(data: data) else {
            /// 未设置加解密的PIN码
            print("解密数据失败")
            doorLock.pin = nil
            pinCallback?("{\"status\": -1, \"error\": \"设备PIN码不正确\"}")
            pinCallback = nil
            return
        }
        guard decrpytedData.count > 9 && decrpytedData[0] == 0xFF && decrpytedData[1] == 0x55 else {
            /// 加解密的PIN码错误
            print("解密数据失败")
            doorLock.pin = nil
            pinCallback?("{\"status\": -1, \"error\": \"设备PIN码不正确\"}")
            pinCallback = nil
            return
        }
        /// 命令类型
        let cmdMode = decrpytedData[3]
        /// 命令
        let cmdType = decrpytedData[4]
        /// 数据部分的长度
        let dataLen = cmdMode == 0x0C ? Int(decrpytedData[2]) - 8 : Int(decrpytedData[2]) - 6
        
        var bodyData: Data?
        if dataLen > 0 {
            bodyData = cmdMode == 0x0C ? decrpytedData.subdata(in: 11..<11+dataLen) : decrpytedData.subdata(in: 9..<9+dataLen)
        }
        print("解密后的数据:\n\(decrpytedData.map {" 0x" + String($0, radix: 16, uppercase: true)}.joined())")
        
        switch cmdType {
        case 0x04: /// 密码错误上报
            let date: Int

            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 2
            cache.time = date
            cacheLog(log: cache)
            print("密码错误")
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x05: /// 钥匙报警
            let date: Int

            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 2
            cache.time = date
            cacheLog(log: cache)
            print("钥匙报警")
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x06: /// 防撬报警
            let date: Int

            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 6
            cache.time = date
            cacheLog(log: cache)
            print("防撬报警")
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x07: /// 低压报警
            print("低压报警")
            
        case 0x08:
            guard let bodyData = bodyData else {
                return
            }
            
            let date: Int
            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 1
            cache.time = date
           
            print("开门上报")
            
            if bodyData.first == 0x01 { // 密码
                print("密码开门")
                cache.number_type = 1
            } else if bodyData.first == 0x02 { // 指纹
                print("指纹开门")
                cache.number_type = 2
            } else if bodyData.first == 0x06 { // 感应
                print("感应卡开门")
                cache.number_type = 6
            }
            
            if let last = bodyData.last, let pwdId = Int(String(last, radix: 10, uppercase: true)) {
                print("用户编号:\(pwdId)")
                if pwdId > 84 && pwdId < 90 {
                    cache.event_type = 7
                }
                cache.number_id = pwdId
            }
            cacheLog(log: cache)
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x09: /// 紧急胁迫报警
            print("紧急胁迫报警")
            
        case 0x0A: /// 门铃上报
            let date: Int

            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 3
            cache.time = date
            cacheLog(log: cache)
            print("门铃上报")
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x0D: /// 注册用户上报
            guard let bodyData = bodyData else {
                return
            }
            
            let date: Int
            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 4
            cache.time = date
            
            
            if bodyData.first == 0x01 { // 密码
                print("注册密码用户")
                cache.number_type = 1
            } else if bodyData.first == 0x02 { // 指纹
                print("注册指纹用户")
                cache.number_type = 2
            } else if bodyData.first == 0x06 { // 感应
                print("注册感应卡用户")
                cache.number_type = 6
            }
            
            if let last = bodyData.last, let pwdId = Int(String(last, radix: 10, uppercase: true)) {
                print("用户编号:\(pwdId)")
                cache.number_id = pwdId
                let number_type = Int(bodyData.first ?? 1)
                cacheVerifcation(lock_id: doorLock.uuid, number_type: number_type, number_id: pwdId)
                
            }
            cacheLog(log: cache)
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x0E: /// 删除用户上报
            guard let bodyData = bodyData else {
                return
            }
            
            let date: Int
            if cmdMode == 0x0C {
                let dateStr = "20" + Array(decrpytedData.subdata(in: 5..<11))
                    .map {
                        String($0, radix: 16, uppercase: false).count > 1 ? String($0, radix: 16, uppercase: false) : "0" + String($0, radix: 16, uppercase: false)
                    }
                    .joined()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                date = Int((formatter.date(from: dateStr) ?? Date()).timeIntervalSince1970)

            } else {
                date = Int(Date().timeIntervalSince1970)
            }
            
            let cache = DoorLockLogCache()
            cache.lock_id = doorLock.uuid
            cache.event_type = 5
            cache.time = date
            
            if bodyData.first == 0x01 { // 密码
                print("删除密码用户")
                cache.number_type = 1
            } else if bodyData.first == 0x02 { // 指纹
                print("删除指纹用户")
                cache.number_type = 2
            } else if bodyData.first == 0x06 { // 感应
                print("删除感应卡用户")
                cache.number_type = 6
            }
            
            if let last = bodyData.last, let pwdId = Int(String(last, radix: 10, uppercase: true)) {
                print("用户编号:\(pwdId)")
                cache.number_id = pwdId
                let _ = deleteVerification(lock_id: doorLock.uuid, number_type: cache.number_type ?? 2, number_id: pwdId)
            }
            cacheLog(log: cache)
            if cmdMode != 0x0C { /// 实时上报回调
                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
            }
            
        case 0x0F: /// 按区段删除用户
            guard let bodyData = bodyData else {
                return
            }
            
            var number_type = 1
            if bodyData.first == 0x01 { // 密码
                print("按区段删除密码用户")
                number_type = 1
            } else if bodyData.first == 0x02 { // 指纹
                print("按区段删除指纹用户")
                number_type = 2
            } else if bodyData.first == 0x06 { // 感应
                print("按区段删除感应卡用户")
                number_type = 6
            }
            
            if let start = Int(bodyData.subdata(in: 1..<3).map { String($0, radix: 16, uppercase: true) }.joined(), radix: 16),
               let end = Int(bodyData.subdata(in: 3..<5).map { String($0, radix: 16, uppercase: true) }.joined(), radix: 16){
                print("用户编号:\(start) - \(end)")
                let _ = rangeDeleteVerification(lock_id: doorLock.uuid, number_type: number_type, start: start, end: end)
            }
            
        case 0x13: /// 设置门锁设置
            guard let bodyData = bodyData else {
                return
            }
            if bodyData.first == 0x00 {
                let json = "{\"status\": 0,\"error\": \"\"}"
                operationFrameResponse.send((cmdType, json))
                print("设置门锁设置成功")
            } else {
                let json = "{\"status\": -1,\"error\": \"设置失败\"}"
                operationFrameResponse.send((cmdType, json))
                print("设置门锁设置失败")
            }
            
        case 0x14: /// 设置门锁常开
            guard let bodyData = bodyData else {
                return
            }
            if bodyData.first == 0x00 {
                let json = "{\"status\": 0,\"error\": \"\"}"
                operationFrameResponse.send((cmdType, json))
                print("设置门锁常开成功")
            } else {
                let json = "{\"status\": -1,\"error\": \"设置失败\"}"
                operationFrameResponse.send((cmdType, json))
                print("设置门锁常开失败")
            }
        case 0x15: /// 远程不带编号增加用户
            guard let bodyData = bodyData else {
                return
            }
            if bodyData.first == 0x00 {
                print("远程不带编号增加用户成功")
                if let last = bodyData.last, let pwdId = Int(String(last, radix: 10, uppercase: true)) {
                    print("用户编号:\(pwdId)")
                    if let lastOperation = lastOperation {
                        switch lastOperation {
                        case .addAnoymousUserRemotely(let type):
                            let cache = DoorLockLogCache()
                            cache.lock_id = doorLock.uuid
                            cache.number_id = pwdId
                            cache.event_type = 4
                            cache.number_type = 1
                            cache.time = Int(Date().timeIntervalSince1970)
                            cacheLog(log: cache)
                            if cmdMode != 0x0C { /// 实时上报回调
                                logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
                            }
                            
                            let number_name = type.number_name ?? "密码 \(pwdId)"
                            let json = addVerification(lock_id: doorLock.uuid, password: type.pwd, number_id: pwdId, number_type: 1, number_name: number_name, valid_time: type.valid_time, role_type: type.role_type)
                            operationFrameResponse.send((cmdType, json))
                            
                        default:
                            break
                        }
                        
                    }
                    
                } else {
                    let json = "{\"status\": -1,\"error\": \"解析用户编号失败\"}"
                    operationFrameResponse.send((cmdType, json))
                }
                
            } else {
                print("远程不带编号增加用户失败")
                let json = "{\"status\": -1,\"error\": \"添加失败\"}"
                operationFrameResponse.send((cmdType, json))
                
            }
        case 0x11: /// 删除用户
            guard let bodyData = bodyData else {
                return
            }
            if bodyData.first == 0x00 {
                print("远程删除用户成功")
                if let lastOperation = lastOperation {
                    switch lastOperation {
                    case .deleteUser(let type, let id):
                        let cache = DoorLockLogCache()
                        cache.lock_id = doorLock.uuid
                        cache.number_id = id
                        cache.event_type = 5
                        cache.number_type = 1
                        cache.time = Int(Date().timeIntervalSince1970)
                        cacheLog(log: cache)
                        if cmdMode != 0x0C { /// 实时上报回调
                            logCallback?("{\"status\": 0, \"data\": {\"log\": \(cache.toJsonStr())}}")
                        }
                        
                        let json = deleteVerification(lock_id: doorLock.uuid, number_type: Int(type.rawValue), number_id: id)
                        operationFrameResponse.send((cmdType, json))
                        
                    default:
                        break
                    }
                    
                }

            } else {
                print("远程删除用户失败")
                let json = "{\"status\": -1,\"error\": \"删除失败\"}"
                operationFrameResponse.send((cmdType, json))
            }
            
        case 0x21: /// 门锁设置查询
            guard let bodyData = bodyData else {
                return
            }
            if bodyData.first == 0xFE {
                let json = "{\"status\": -1,\"error\": \"查询失败\"}"
                operationFrameResponse.send((cmdType, json))
                print("门锁设置查询失败")
            } else {
                var iter = bodyData.makeIterator()
                let byte = iter.next()
                if byte == 0x01 { /// 设置：语言选择、音量大小、常开模式等
                    /// 0x00――简体中文 0x01――英文
                    let lang = iter.next() == 0x01 ? "1" : "0"
                    /// 预留字节
                    let reserve = iter.next()
                    /// 音量
                    let volByte = iter.next()
                    let vol: String
                    /// 0x01――高 0x03――低 0x04――静音 0x02-中
                    if volByte == 0x01 {
                        vol = "1"
                    } else if volByte == 0x02 {
                        vol = "2"
                    } else if volByte == 0x03 {
                        vol = "3"
                    } else {
                        vol = "4"
                    }
                    /// 常开
                    let alwaysOpen = iter.next() == 0x00 ? 0 : 1
                    print("门锁当前设置:\n 语言: \(lang) 保留位: \(String(describing: reserve)) 音量: \(vol) 常开状态: \(alwaysOpen)")
                    let json = "{\"status\": 0,\"error\": \"\", \"data\": {\"lang\": \(lang), \"volume\": \(vol), \"normally_open\": \(alwaysOpen)}}"
                    operationFrameResponse.send((cmdType, json))

                } else if byte == 0x02 { /// 报警状态
                    let state = iter.next()
                    switch state {
                    case 0x00:
                        print("门锁当前报警状态: 正常状态")
                    case 0x01:
                        print("门锁当前报警状态: 键盘已锁")
                    case 0x04:
                        print("门锁当前报警状态: 钥匙报警")
                    case 0x08:
                        print("门锁当前报警状态: 低压报警")
                    case 0x10:
                        print("门锁当前报警状态: 紧急胁迫报警")
                    default:
                        break
                    }
                } else if byte == 0x05 { /// 锁体开关状态
                    let state = iter.next()
                    if state == 0x00 {
                        print("锁体开关状态: 没有开关闭合")
                    } else {
                        print("锁体开关状态: \(String(describing: state))")
                    }
                }
                
            }
            
        case 0x22: /// 查询电量
            guard let bodyData = bodyData else {
                return
            }
            if bodyData.first == 0xFE {
                print("查询电量失败")
                operationFrameResponse.send((cmdType, "{\"status\": -1, \"error\": \"查询电量失败\"}"))
            } else {
                if let p = bodyData.first {
                    print("查询电量成功: \(Int(p))%")
                    let json = "{\"status\": 0, \"error\": \"\", \"data\": {\"power\": \(Int(p)), \"name\": \"\(doorLock.name)\"}}"
                    operationFrameResponse.send((cmdType, json))
                } else {
                    operationFrameResponse.send((cmdType, "{\"status\": -1, \"error\": \"查询电量失败\"}"))
                }
                
            }
            
        case 0x26: /// 设置系统时间
            guard let bodyData = bodyData else {
                return
            }
            
            if pinCallback != nil, let doorLock = self.doorLock {
                cacheDoorLock(doorLock: doorLock)
                sendFrameData(.queryRegisteredUser(type: .all))
                sendFrameData(.queryLog)
                pinCallback?("{\"status\": 0, \"error\": \"\"}")
                pinCallback = nil
            }
            
            
            if bodyData.first == 0x00 { /// 设置成功
                let json = "{\"status\": 0,\"error\": \"\"}"
                operationFrameResponse.send((cmdType, json))
                print("设置系统时间成功")
            } else { /// 设置失败
                let json = "{\"status\": -1,\"error\": \"设置系统时间失败\"}"
                operationFrameResponse.send((cmdType, json))
                print("设置系统时间失败")
            }
            
        case 0x28: /// 用户已注册编号查询
            guard let bodyData = bodyData else {
                return
            }
            
            func handleResult(data: Data) {
                var _data = data
                var iter = _data.makeIterator()
                let flag = iter.next()
                if flag == 0x01 { // 指纹
                    let _ = iter.next()
                    let _ = iter.next()
                    var fgUsers = ""
                    for _ in 0..<13 {
                        if let byte = iter.next() {
                            fgUsers = fgUsers + byte.bits().replacingOccurrences(of: " ", with: "").reversed()
                        }
                    }
                    _data.removeSubrange(0..<16)
                    var registered = [Int]()
                    for (n, s) in fgUsers.enumerated() {
                        if s == "1" {
                            registered.append(n)
                        }
                    }
                    print("已注册指纹编号: \(registered)")
                    cacheVerifcations(lock_id: doorLock.uuid, number_type: 2, number_id: registered)
                    handleResult(data: _data)
                } else if flag == 0x02 { // 密码
                    let _ = iter.next()
                    let _ = iter.next()
                    var pwdUsers = ""
                    for _ in 0..<13 {
                        if let byte = iter.next() {
                            pwdUsers = pwdUsers + byte.bits().replacingOccurrences(of: " ", with: "").reversed()
                        }
                    }
                    _data.removeSubrange(0..<16)
                    var registered = [Int]()
                    for (n, s) in pwdUsers.enumerated() {
                        if s == "1" {
                            registered.append(n)
                        }
                    }
                    print("已注册密码编号: \(registered)")
                    cacheVerifcations(lock_id: doorLock.uuid, number_type: 1, number_id: registered)
                    handleResult(data: _data)
                } else if flag == 0x03 { // 卡
                    let _ = iter.next()
                    let _ = iter.next()
                    var nfcUsers = ""
                    for _ in 0..<23 {
                        if let byte = iter.next() {
                            nfcUsers = nfcUsers + byte.bits().replacingOccurrences(of: " ", with: "").reversed()
                        }
                    }
                    _data.removeSubrange(0..<26)
                    var registered = [Int]()
                    for (n, s) in nfcUsers.enumerated() {
                        if s == "1" {
                            registered.append(n)
                        }
                    }
                    print("已注册卡编号: \(registered)")
                    cacheVerifcations(lock_id: doorLock.uuid, number_type: 6, number_id: registered)
                    handleResult(data: _data)
                } else {
                    return
                }
                
            }
            
            if bodyData.first == 0xFE {
                print("查询用户已注册编号失败")
            } else {
                handleResult(data: bodyData)
            }
            
        default:
            break
        }
        
    }
    
}
